#pragma once

#include "Sock.hpp"
#include "Protocol.hpp"
#include <pthread.h>
#include <functional>

namespace tcpserver_ns
{
    using namespace protocol_ns;

    class TcpServer; // 声明
    using func_t = std::function<Response(const Request&)>;

    // 多线程需要处理的数据
    struct ThreadData
    {
        ThreadData(int sock, std::string ip, uint16_t port, TcpServer *tsvrp)
            : _sock(sock), _ip(ip), _port(port), _tsvrp(tsvrp)
        {
        }
        ~ThreadData() {}

        int _sock;
        std::string _ip;
        uint16_t _port;
        TcpServer *_tsvrp;
    };

    class TcpServer
    {
    public:
        TcpServer(const uint16_t &port)
            : _port(port)
        {
        }

        // 初始化服务器
        void InitServer()
        {
            // 获取文件描述符
            _listensock.Socket();
            // 绑定
            _listensock.Bind(_port);
            // 监听
            _listensock.Listen();
            logMessage(Info, "init server done, listensock: %d", _listensock.getFd());
        }

        static void *ThreadRoutine(void *args) // 这里定义静态成员是为了防止：隐式接收this参数
        {
            // 线程分离：此后无需对当前线程进行回收
            pthread_detach(pthread_self());
            ThreadData *td = static_cast<ThreadData *>(args); // 类型转换
            // 回调处理业务
            td->_tsvrp->ServerIO(td->_sock, td->_ip, td->_port);
            // 释放资源
            delete td;

            return nullptr;
        }

        //多线程处理的业务
        void ServerIO(int sock, const std::string &ip, const uint16_t &port)
        {

        }

        void Start()
        {
            while (true)
            {
                std::string clientip;
                uint16_t clientport;

                // 接收连接
                int sock = _listensock.Accept(&clientip, &clientport);
                if (sock < 0)
                    continue; // 获取连接失败
                logMessage(Debug, "get a new client, client info : [%s:%d]", clientip.c_str(), clientport);

                // 创建多线程
                pthread_t tid;
                ThreadData *td = new ThreadData(sock, clientip, clientport, this); // 传this是为了能调用类中成员
                pthread_create(&tid, nullptr, ThreadRoutine, td);
            }
        }

        ~TcpServer() {}

    private:
        uint16_t _port;
        Sock _listensock;
    };
}